/************ Private Header Files **************/
#include "HsTypes.h"
#include "PhyDebug.h"
#include "PhyStruct.h"
#include "PmdGlobals.h"
#include "PhyConstants.h"
#include "tables.h"
#include "tx_functions.h"
#include "iqdma_3500.h"
#include "icrdefs_3500.h"
#include "txtables.h"
#include "thread_globals.h"
#include "threads_common.h"//add 627

static inline
void send_16(hs_int16_t *outI, hs_int16_t *outQ, hs_int16_t *inI, hs_int16_t *inQ)
{
	__sb_rcopy(outI, inI);
	__sb_rcopy(outQ, inQ);
}


static inline hs_int32_t
wait_buffer(
				hs_int32_t subbuff_toggle,
				hs_int16_t **psTxOutDtoAPtrI,
				hs_int16_t **psTxOutDtoAPtrQ,
				hs_int16_t *psTxDtoAStartI,
				hs_int16_t *psTxDtoAStartQ
			)
{
	/** Wait till prev sub-buffer is Txmitted **/
	wait_sub_buffer_filled();
	reset_sub_buffer_interrupt();

	subbuff_toggle ^= 1;

	if(subbuff_toggle){
		*psTxOutDtoAPtrI = psTxDtoAStartI + SUB_BUF_SIZE_TX;
		*psTxOutDtoAPtrQ = psTxDtoAStartQ + SUB_BUF_SIZE_TX;
	}
	else{
		*psTxOutDtoAPtrI = psTxDtoAStartI;
		*psTxOutDtoAPtrQ = psTxDtoAStartQ;
	}

	return subbuff_toggle;
}

void
send_55mbps_3(
                struct HS_PhyTx11bStr  *HS_PhyTx11bPtrTh,
                ePHYSTATES_TH  *ePhyState,
                hs_int16_t  *restrict psCckDqpskSeq,
                hs_int16_t * psTxDtoAStartI,
                hs_int16_t * psTxDtoAStartQ
            )
{
	hs_int32_t i;
	hs_int16_t zeros[16]= {0};
	hs_int32_t tempreg_toggle;
	hs_uint32_t *uiTempReg_shared;
	hs_uint32_t uiTempReg;

    hs_uint16_t usLength;
	hs_int32_t siPayloadBitCount;
	hs_int32_t symbol_count;
    hs_int32_t subbuff_toggle;

    hs_int16_t * psTxOutDtoAPtrI;
    hs_int16_t * psTxOutDtoAPtrQ;

	hs_uint32_t d2a_base = ICR_ADDRESS_CORE_CHANNEL(TX_CORE, TX_PSD);

    uiTempReg_shared = HS_PhyTx11bPtrTh->uiTempReg_shared;
    usLength = HS_PhyTx11bPtrTh->usLength;
    psTxOutDtoAPtrI = HS_PhyTx11bPtrTh->psTxDtoABufferI;
    psTxOutDtoAPtrQ = HS_PhyTx11bPtrTh->psTxDtoABufferQ;

	siPayloadBitCount = 0;

	subbuff_toggle = HS_PhyTx11bPtrTh->subbuff_toggle;
    symbol_count = 0;
	tempreg_toggle = 0;

    while(1){

    	while(tx_thread2to3_flag1 == 0){
    		SPIN(2);
        }

    	for(i=0; i<2; i++){
			uiTempReg = uiTempReg_shared[tempreg_toggle*2+i];

			send_16(psTxOutDtoAPtrI, psTxOutDtoAPtrQ, &psCckDqpskSeq[uiTempReg], &psCckDqpskSeq[uiTempReg+16]);

	        psTxOutDtoAPtrI += (16);
	        psTxOutDtoAPtrQ += (16);

	        symbol_count++;

	        if(symbol_count == 11){

	        	symbol_count = 0;
	        	subbuff_toggle = wait_buffer(subbuff_toggle,
	    									&psTxOutDtoAPtrI,
	    									&psTxOutDtoAPtrQ,
	    									psTxDtoAStartI,
	    									psTxDtoAStartQ
									);
	        }
    	}

    	tx_thread2to3_flag1 = 0;

    	tempreg_toggle ^= 1;

		siPayloadBitCount += 8;
        if(siPayloadBitCount == (usLength*8))
        {
        	*ePhyState  = PHY_STATE_SWITCH_OFF_TH;
           break;
        }/* if siStateCount */
    }

    /** Wait till last sub-buffer is Txmitted **/
    wait_sub_buffer_filled();
	reset_sub_buffer_interrupt();

	/** Wait for remaining samples **/
	if(symbol_count != 0){

		while(ICR_GET(d2a_base, REG_D2AISTR) < ((hs_uint32_t)(psTxOutDtoAPtrI+4) & 0x0fffff)){
			__sb_barrier();
		}
	}

	HS_PhyTx11bPtrTh->tx_status_l = HS_COMPLETE;
}

static inline hs_int16_t
send_cck_samps(
				hs_int16_t ssPrevSymb,
				hs_int32_t *flip_flag,
				hs_int32_t (*cck_index_11)[256],
				hs_uint8_t *ucInputBit_shared,
				hs_int16_t **psTxOutDtoAPtrI,
			    hs_int16_t **psTxOutDtoAPtrQ,
			    hs_int16_t *psTxDtoAStartI,
			    hs_int16_t *psTxDtoAStartQ,
			    hs_int32_t *symbol_count,
			    hs_int32_t *subbuff_toggle
			)
{
    hs_int16_t *offsetI;
    hs_int16_t *offsetQ;
    hs_uint8_t ucInputBit;

	ucInputBit = ucInputBit_shared[*flip_flag];
	(*flip_flag) ^= 1;
	offsetI = (hs_int16_t *)cck_index_11[ssPrevSymb][ucInputBit];
	offsetQ = (hs_int16_t *)cck_index_11[4+ssPrevSymb][ucInputBit];
	ssPrevSymb = cck_index_11[8+ssPrevSymb][ucInputBit];

	__sb_rcopy(*psTxOutDtoAPtrI, offsetI);
	__sb_rcopy(*psTxOutDtoAPtrQ, offsetQ);

	*psTxOutDtoAPtrI += 16;
	*psTxOutDtoAPtrQ += 16;

	(*symbol_count)++;

	if(*symbol_count == 11){

		*subbuff_toggle = wait_buffer(*subbuff_toggle,
								psTxOutDtoAPtrI,
								psTxOutDtoAPtrQ,
								psTxDtoAStartI,
								psTxDtoAStartQ
						);
		*symbol_count = 0;
	}

	return ssPrevSymb;
}


void
send_11mbps_3(
                struct HS_PhyTx11bStr  *HS_PhyTx11bPtrTh1,
                ePHYSTATES_TH	*ePhyState,
                hs_int32_t (*cck_index_11)[256],
                hs_int16_t 	*psTxDtoAStartI,
                hs_int16_t 	*psTxDtoAStartQ
            )
{
	//int tic1, tic2;
	hs_int32_t i;
	hs_int16_t zeros[16] = {0};
	hs_int32_t flip_flag;
	hs_int32_t count;
    hs_int16_t ssPrevSymb;
    hs_uint16_t usLength;
    hs_int32_t symbol_count;
    hs_int32_t subbuff_toggle;

    hs_int16_t 	*psTxOutDtoAPtrI;
    hs_int16_t 	*psTxOutDtoAPtrQ;
    hs_uint8_t *ucInputBit_shared;

    ssPrevSymb = HS_PhyTx11bPtrTh1->ucPrevSymb;
    usLength = HS_PhyTx11bPtrTh1->usLength;

    psTxOutDtoAPtrI = HS_PhyTx11bPtrTh1->psTxDtoABufferI;
    psTxOutDtoAPtrQ = HS_PhyTx11bPtrTh1->psTxDtoABufferQ;

    subbuff_toggle	= HS_PhyTx11bPtrTh1->subbuff_toggle;
    ucInputBit_shared = HS_PhyTx11bPtrTh1->ucInputBit_shared_11;

    symbol_count = 0;
    count = usLength;
	flip_flag = 0;

    while(count-- > 0){

    	while(tx_thread2to3_flag1 == 0){
    		SPIN(2);
        }

    	//tic1 = __sb_cfsr(MACH_CYC);

    	ssPrevSymb = send_cck_samps(
    					ssPrevSymb,
    					&flip_flag,
    					cck_index_11,
    					ucInputBit_shared,
    					&psTxOutDtoAPtrI,
    				    &psTxOutDtoAPtrQ,
    				    psTxDtoAStartI,
    				    psTxDtoAStartQ,
    				    &symbol_count,
    				    &subbuff_toggle
    				);

		tx_thread2to3_flag1 = 0;

		//tic2 = __sb_cfsr(MACH_CYC);
		//__putstring("cyc = %d\n", tic2-tic1);
    }

    //add noise 0
	   for(i = 0;i< SUB_BUF_SIZE_TX;i+=16)
		{
		   __sb_rcopy(psTxOutDtoAPtrI, &zeros);
		   __sb_rcopy(psTxOutDtoAPtrQ, &zeros);

		   psTxOutDtoAPtrI += 16;
		   psTxOutDtoAPtrQ += 16;

		}
		 wait_sub_buffer_filled();
		 reset_sub_buffer_interrupt();

		 for(i = 0;i< SUB_BUF_SIZE_TX;i+=16)
		{
		   __sb_rcopy(psTxOutDtoAPtrI, &zeros);
		   __sb_rcopy(psTxOutDtoAPtrQ, &zeros);

		   psTxOutDtoAPtrI += 16;
		   psTxOutDtoAPtrQ += 16;

		}
		 //wait_sub_buffer_filled();
		 //reset_sub_buffer_interrupt();
		//end add

    /** Wait till last sub-buffer is Txmitted **/
    wait_sub_buffer_filled();
	reset_sub_buffer_interrupt();

	/** Wait for remaining samples **/
	if(symbol_count != 0){

		hs_uint32_t d2a_base = ICR_ADDRESS_CORE_CHANNEL(TX_CORE, TX_PSD);

		while(ICR_GET(d2a_base, REG_D2AISTR) < ((hs_uint32_t)(psTxOutDtoAPtrI+4) & 0x0fffff)){
			__sb_barrier();
		}
	}

	HS_PhyTx11bPtrTh1->tx_status_l = HS_COMPLETE;

    *ePhyState  = PHY_STATE_SWITCH_OFF_TH;
}


void
FnThread23(void *t)
{
  hs_int16_t *psTxDtoAStartI;
  hs_int16_t *psTxDtoAStartQ;

  ePHYSTATES_TH  ePhyState;

  /* Tx Variables */
  struct HS_PhyTx11bStr  *HS_PhyTx11bPtrTh1;

  HS_PhyTx11bPtrTh1 = &sPhyTx11bStr;

  psTxDtoAStartI = HS_PhyTx11bPtrTh1->psTxDtoAStartI;
  psTxDtoAStartQ = HS_PhyTx11bPtrTh1->psTxDtoAStartQ;

  while(tx_data_flag3 == 0){
	  SPIN(2);
  }
  tx_data_flag3 = 0;

  ePhyState = (ePHYSTATES_TH)HS_PhyTx11bPtrTh1->ePhyState;

  switch(ePhyState)
  {
     case PHY_STATE_TX_SEND_PAYLOAD_5DOT5MBPS_TH:
     {
         send_55mbps_3(
            HS_PhyTx11bPtrTh1,
            &ePhyState,
            asCckDqpskSeq,
            psTxDtoAStartI,
            psTxDtoAStartQ
         );

        break;
     }/* case PHY_STATE_TX_SEND_PAYLOAD_5DOT5MBPS_TH */

     case PHY_STATE_TX_SEND_PAYLOAD_11MBPS_TH:
     {
    	 send_11mbps_3(
    	                 HS_PhyTx11bPtrTh1,
    	                 &ePhyState,
    	                 cck_index_11,
                         psTxDtoAStartI,
                         psTxDtoAStartQ
    	             );

        break;
     }/* case PHY_STATE_TX_SEND_PAYLOAD_11MBPS_TH */

     /* ********************************* TX_ENDS ******************* */

     case PHY_STATE_SWITCH_OFF_TH:
     {
         break;
     }/* case PHY_STATE_SWITCH_OFF_TH */

     default:
     	 break;

  }/* switch ePhyState */

}/* Function */
